/*
 * Copyright (c) 2025 彭友聪
 * nativePC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 *
 * Author: 彭友聪
 * email：2923616405@qq.com
 * date: 2025/10/8 09:34
 * file: ${FILE_NAME}
 * product: DevEco Studio
 * LICENSE: MulanPSL-2.0
 * */
//
// Created on 2025/10/8.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef NATIVEPC_ARKUINODE_H
#define NATIVEPC_ARKUINODE_H
#include "ArkUIBaseNode.h"
#include "NativeModule.h"
#include <arkui/native_node.h>
#include <arkui/native_type.h>

namespace NativeModule
{
    class ArkUINode : public ArkUIBaseNode
    {
        private:
            std::function<void(ArkUI_NodeEvent *event)> onClick_;
            std::function<void()> onDisappear_;
            std::function<void()> onAppear_;
            std::function<void(ArkUI_NodeEvent *event)> onDragStart_;
            std::function<void(ArkUI_NodeEvent *event)> onDragDrop_;
            std::function<void(int32_t type, float x, float y)> onTouch_;

        protected:
            void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override
            {
                nativeModule_->addChild(handle_, child->GetHandle());
            }

            void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override
            {
                nativeModule_->removeChild(handle_, child->GetHandle());
            }

            void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override
            {
                nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
            }
            // 事件监听器函数指针。
            static void NodeEventReceiver(ArkUI_NodeEvent *event)
            {
                // 获取事件发生的UI组件对象。
                auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event);
                // 获取保持在UI组件对象中的自定义数据，返回封装类指针。
                auto *node = reinterpret_cast<ArkUINode *>(
                    NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
                // 基于封装类实例对象处理事件。
                node->ProcessNodeEvent(event);
            }
            void ProcessNodeEvent(ArkUI_NodeEvent *event)
            {
                auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
                    switch (eventType) {
                        case NODE_ON_CLICK_EVENT:
                            {
                                    if (onClick_) {
                                        onClick_(event);
                                    }
                                break;
                            }
                        case NODE_TOUCH_EVENT:
                            {
                                    if (onTouch_) {
                                        auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
                                        float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
                                        float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
                                        auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent);
                                        onTouch_(type, x, y);
                                    }
                            }
                        case NODE_EVENT_ON_DISAPPEAR:
                            {
                                    if (onDisappear_) {
                                        onDisappear_();
                                    }
                                break;
                            }
                        case NODE_EVENT_ON_APPEAR:
                            {
                                    if (onAppear_) {
                                        onAppear_();
                                    }
                                break;
                            }
                        case NODE_ON_DRAG_START:
                            {
                                    if (onDragStart_) {
                                        onDragStart_(event);
                                    }
                                break;
                            }
                        case NODE_ON_DROP:
                            {
                                    if (onDragDrop_) {
                                        onDragDrop_(event);
                                    }
                                break;
                            }
                        default:
                            {
                                // 组件特有事件交给子类处理
                                OnNodeEvent(event);
                            }
                    }
            }
            virtual void OnNodeEvent(ArkUI_NodeEvent *event) {}

        public:
            explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle)
            {
                nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
                // 事件触发时需要通过函数获取对应的事件对象，这边通过设置节点自定义数据将封装类指针保持在组件上，方便后续事件分发。
                nativeModule_->setUserData(handle_, this);
                // 注册节点监听事件接受器。
                nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
            }

            ~ArkUINode() override
            {
                    if (onClick_) {
                        nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK_EVENT);
                    }
                    if (onTouch_) {
                        nativeModule_->unregisterNodeEvent(handle_, NODE_TOUCH_EVENT);
                    }
                    if (onDisappear_) {
                        nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR);
                    }
                    if (onAppear_) {
                        nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_APPEAR);
                    }
                nativeModule_->removeNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
            }
            // 处理通用事件。
            void RegisterOnClick(const std::function<void(ArkUI_NodeEvent *event)> &onClick)
            {
                assert(handle_);
                onClick_ = onClick;
                // 注册点击事件。
                nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK_EVENT, 0, globalParams);
            }
            void RegisterNodeEvent(ArkUI_NodeHandle node,ArkUI_NodeEventType eventType, int32_t targetId, void* userData)
            {
                nativeModule_->registerNodeEvent(node, eventType, targetId, userData);
            }
            void RegisterNodeEventReceiver(void (*eventReceiver)(ArkUI_NodeEvent* event))
            {
                nativeModule_->addNodeEventReceiver(handle_, eventReceiver);
            }
            void RegisterDragStart(const std::function<void(ArkUI_NodeEvent *event)> &onDragStart)
            {
                assert(handle_);
                onDragStart_ = onDragStart;
                nativeModule_->registerNodeEvent(handle_, NODE_ON_DRAG_START, 0, globalParams);
            }
            void RegisterDragDrop(const std::function<void(ArkUI_NodeEvent *event)> &onDragDrop)
            {
                assert(handle_);
                onDragDrop_ = onDragDrop;
                nativeModule_->registerNodeEvent(handle_, NODE_ON_DROP, 0, globalParams);
            }

            void RegisterOnTouch(const std::function<void(int32_t type, float x, float y)> &onTouch)
            {
                assert(handle_);
                onTouch_ = onTouch;
                // 注册触碰事件。
                nativeModule_->registerNodeEvent(handle_, NODE_TOUCH_EVENT, 0, nullptr);
            }

            void RegisterOnDisappear(const std::function<void()> &onDisappear)
            {
                assert(handle_);
                onDisappear_ = onDisappear;
                // 注册卸载事件。
                nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr);
            }

            void RegisterOnAppear(const std::function<void()> &onAppear)
            {
                assert(handle_);
                onAppear_ = onAppear;
                // 注册挂载事件。
                nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr);
            }
            // NDK 相关通用属性调用封装
            void SetWidth(float width)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.f32 = width}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
            }
            void SetPercentWidth(float percent)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.f32 = percent}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
            }
            void SetHeight(float height)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.f32 = height}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
            }
            void SetPercentHeight(float percent)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.f32 = percent}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
            }
            void SetBackgroundColor(uint32_t color)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.u32 = color}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
            }
            void SetMargin(uint32_t margin)
            {
                assert(handle_);
                ArkUI_NumberValue value[] = {{.u32 = margin}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, NODE_MARGIN, &item);
            }
            void SetPadding(float padding, bool isPercent = false)
            {
                ArkUI_NumberValue value[] = {{.f32 = padding}};
                ArkUI_AttributeItem item = {value, 1};
                nativeModule_->setAttribute(handle_, isPercent ? NODE_PADDING_PERCENT : NODE_PADDING, &item);
            }
    };
} // namespace NativeModule

#endif // NATIVEPC_ARKUINODE_H
